import breve
import random

class Controller(breve.Control):
	def __init__(self):
		breve.Control.__init__(self)
		self.setBackgroundColor(breve.vector())
		self.enableLighting()
		env = Room(breve.vector(10, 0, 10), 10, 
			[ExitBot(10, breve.vector(5, 0, -5)),
			 ExitBot(10, breve.vector(5, 0, -5))])
	
	def iterate(self):
		breve.Control.iterate(self)
		self.updateNeighbors()	
	
class GridBot(breve.Mobile):
	def __init__(self, unit):
		breve.Mobile.__init__(self)
		self.unit = unit
		self.setShape(breve.createInstances(breve.Cube, 1).initWith(
			breve.vector(unit, unit, unit)))
		self.setColor(breve.vector(1, 0, 0))
		self.handleCollisions('GridBot', 'botCollision')
	
	def iterate(self):
		breve.Mobile.iterate(self)
		self.neighborList = self.getNeighbors()
		self.look("Right", "Center")	
		
	def botCollision(self):
		self.setColor(breve.vector(
			breve.randomExpression(1),
			breve.randomExpression(1),
			breve.randomExpression(1)))
		
	def look(self, xDirection, zDirection):
		x = 0
		z = 0
	
		if xDirection != "Center":
			if xDirection == "Left": x -= (self.unit - 1)
			else: x += (self.unit - 1)

		if zDirection != "Center":
			if zDirection == "Up": z -= (self.unit - 1)
			else: z += (self.unit - 1)
		
		while len(self.neighborList) > 0:
			neighbor = self.neighborList.pop()
			if (neighbor.getLocation()[0] > self.getLocation()[0] - self.unit / 2 + x and
			    neighbor.getLocation()[0] < self.getLocation()[0] - self.unit / 2 + self.unit + x and
			    neighbor.getLocation()[2] < self.getLocation()[2] + self.unit / 2 + z and
				neighbor.getLocation()[2] > self.getLocation()[2] + self.unit / 2 - self.unit + z):
					neighbor.setColor(breve.randomExpression(breve.vector(1, 1, 1)))
			
	def walk(self, xDirection, zDirection):
		x = 0
		z = 0
		
		if xDirection != "Center":
			if xDirection == "Left": x -= self.unit
			else: x += self.unit	
	
		if zDirection != "Center":
			if zDirection == "Up": z -= self.unit
			else: z += self.unit
	
		self.move(breve.vector(
			self.getLocation()[0] + x, 
			self.getLocation()[1], 
			self.getLocation()[2] + z))

class ExitBot(GridBot):
	def __init__(self, unit, exit):
		GridBot.__init__(self, unit)
		self.exit = exit
		self.getOut = False	
	
	def iterate(self):
		GridBot.iterate(self)
		exitDirection = self.getExitDirection()
		print exitDirection
		print self.getLocation()
		print self.exit
		self.walk(exitDirection[0], exitDirection[1])	
			
	def getExitDirection(self):
		x = "Center"
		z = "Center"
		if self.getLocation()[0] < self.exit[0]: x = "Right"
		if self.getLocation()[0] > self.exit[0]: x = "Left"
		if self.getLocation()[2] < self.exit[2]: z = "Down"
		if self.getLocation()[2] > self.exit[2]: z = "Up"
		return [x, z]		
			
class Room(breve.Real):
	def __init__(self, dim, unit, botList):
		breve.Real.__init__(self)
		self.unit = unit
		self.width = dim[0]
		self.height = dim[2]
		self.getController().pointCamera(
			breve.vector(self.width * unit / 2, 0, -self.height * unit / 2), 
			breve.vector(0, 100, self.height * unit))
		self.getController().moveLight(
			breve.vector(self.width * unit / 2, 10, -self.height * unit / 2))
		
		for x in range(0, self.width):
			Wall(breve.vector(x * unit + unit / 2, unit / 2, 0), 
				 breve.vector(unit, unit, .1))
			Wall(breve.vector(x * unit + unit / 2, unit / 2, -self.height * unit), 
				 breve.vector(unit, unit, .1))
		
		for z in range(0, self.height):
			Wall(breve.vector(0, unit / 2, -z * unit - unit / 2), 
				 breve.vector(.1, unit, unit))
			Wall(breve.vector(self.width * unit, unit / 2, -z * unit - unit / 2), 
				 breve.vector(.1, unit, unit))

		for z in range(0, self.height):
			for x in range(0, self.width):
				Ground(breve.vector(x * unit + unit / 2, 0, -z * unit - unit / 2), 
					   breve.vector(unit, .1, unit))
		
		if len(botList) > self.width * self.height:
			print "Too many bots!"
		self.placeBots(botList)	
		
	def placeBots(self, botList):
		positions = []
		positionCount = self.width * self.height
		
		for i in range(0, positionCount):
			positions.append(True)

		while len(botList) > 0:
			while True:
				spot = random.randint(0, positionCount - 1)
				if positions[spot]: break
				
			positions[spot] = False	
			bot = botList.pop()
			bot.setNeighborhoodSize(self.unit * 2)
			bot.move(breve.vector(int(spot % self.height) * self.unit + self.unit / 2, self.unit / 2, 
								 -int(spot / self.height) * self.unit - self.unit / 2))

	def getWidth(self): return self.width
	def getHeight(self): return self.height
	def getUnit(self): return self.unit
	
class Obstruction(breve.Stationary):
	def __init__(self, position, dimension, color):
		breve.Stationary.__init__(self)
		self.setTexture(-1)
		self.setShape(breve.createInstances(breve.Cube, 1).initWith(dimension))
		self.setColor(color)
		self.move(position)
	
class Wall(Obstruction):
	def __init__(self, position, dimension):
		Obstruction.__init__(self, position, dimension, breve.vector(1.0, 1.0, 1.0))
		self.setBitmapTransparency(0.5)	
		
class Ground(Obstruction):
	def __init__(self, position, dimension):
		Obstruction.__init__(self, position, dimension, breve.vector(0.0, 0.3, 0.0))
		self.setBitmapTransparency(0.5)
		
Controller()